iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 11
0
自我挑戰組

Android的學習歷程系列 第 11

[Day 11]Android程式設計-使用OpenData資料製作app(七)(kotlin)

  • 分享至 

  • xImage
  •  

今天要來完成最後的部分,要依據選擇的景點來搜尋空汙情況並且將資料顯示在spinner下方,圖示會依據空汙情況來做改變。

在kotlin中使用spinner只要輸入元件名稱便能夠直接做使用了。

tour_spinner.adapter = spinnerList

adapter直接放入一個ArrayAdapter便能夠完成spinner的顯示,ArrayAdapter要放入的值如下,nameList便是先前取得的景點列表。

val spinnerList: ArrayAdapter<String> = ArrayAdapter(context!!, R.layout.spinner_item, nameList)

完成後來設定點擊事件,在onItemSelectedListener中有兩個方法能做判斷,分別是未選擇時與選擇時的情況。

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val spinnerList: ArrayAdapter<String> = ArrayAdapter(context!!, R.layout.spinner_item, nameList)
        tour_spinner.adapter = spinnerList
        tour_spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
            override fun onNothingSelected(parent: AdapterView<*>?) {
              
            }

            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
              
            }
        }
    }

選擇完地點後還需要判斷距離來選擇最近檢測站數值。

 //計算兩點距離
    fun getDistance(latitudeA: Double, longitudeA: Double, latitudeB: Double, longitudeB: Double): Float {
        val locationA = Location("point A")
        val locationB = Location("point B")

        //A點經、緯度
        locationA.longitude = longitudeA
        locationA.latitude = latitudeA

        //B點經、緯度
        locationB.longitude = longitudeB
        locationB.latitude = latitudeB

        val distance: Float = locationA.distanceTo(locationB)

        return distance
    }

後面還會有空氣資料需要處理。

class Air {
    var site: String? = null
    var county: String? = null
    var pm25: String? = null
    var dataCreationDate: String? = null
    var itemUnit: String? = null
}

開頭的地方有多幾行宣告。

class SelectFragment : Fragment(), View.OnClickListener {

    companion object

    val TAG = SelectFragment::class.java.simpleName

    //旅遊資料
    private lateinit var tours: ArrayList<Tour>
    private lateinit var tour: Tour

    private lateinit var nameList: ArrayList<String>

    //空氣資料
    private lateinit var airs: ArrayList<Air>
    private lateinit var air: Air

    //最短距離
    var minDistance = 0.0f
    var minDistanceArea = ""
    var minDistanceAir = ""
    .....

最後在spinner的onItemSelected下新增判斷便能夠依據距離來顯示所要呈現的資料。

class SelectFragment : Fragment(), View.OnClickListener {

    companion object

    val TAG = SelectFragment::class.java.simpleName

    //旅遊資料
    private lateinit var tours: ArrayList<Tour>
    private lateinit var tour: Tour

    private lateinit var nameList: ArrayList<String>

    //空氣資料
    private lateinit var airs: ArrayList<Air>
    private lateinit var air: Air

    //最短距離
    var minDistance = 0.0f
    var minDistanceArea = ""
    var minDistanceAir = ""

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        getAssetsStream()
        return inflater.inflate(R.layout.fragment_select, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val spinnerList: ArrayAdapter<String> = ArrayAdapter(context!!, R.layout.spinner_item, nameList)
        tour_spinner.adapter = spinnerList
        tour_spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
                //選擇地點
                if (position != 0) {
                    Log.e("選擇的地點 ", "tour name : ${tours[position - 1].name}")

                    //取得地點經緯度
                    val getLongitudeA: Double = tours[position - 1].eastL!!.toDouble()
                    val getLatitudeA: Double = tours[position - 1].northL!!.toDouble()

                    //取得最短距離檢測站空氣品質
                    for (i in 0 until airs.size) {
                        when {
                            airs[i].site.equals("西屯") -> {
                                val areaDis = getDistance(getLongitudeA, getLatitudeA, 120.616917, 24.162197)
                                Log.e("空汙 ", "air p : $areaDis")
                                Log.e("minDistance ", "air p : $minDistance")
                                if (minDistance == 0.0f) {
                                    minDistance = areaDis
                                    minDistanceArea = "西屯"
                                    minDistanceAir = airs[i].pm25!!
                                } else if (minDistance > areaDis) {
                                    minDistance = areaDis
                                    minDistanceArea = "西屯"
                                    minDistanceAir = airs[i].pm25!!
                                }
                            }
                            airs[i].site.equals("忠明") -> {
                                val areaDis = getDistance(getLongitudeA, getLatitudeA, 120.641092, 24.151958)
                                Log.e("空汙 ", "air p : $areaDis")
                                Log.e("minDistance ", "air p : $minDistance")
                                if (minDistance == 0.0f) {
                                    minDistance = areaDis
                                    minDistanceArea = "忠明"
                                    minDistanceAir = airs[i].pm25!!
                                } else if (minDistance > areaDis) {
                                    minDistance = areaDis
                                    minDistanceArea = "忠明"
                                    minDistanceAir = airs[i].pm25!!
                                }
                            }
                            airs[i].site.equals("大里") -> {
                                val areaDis = getDistance(getLongitudeA, getLatitudeA, 120.677689, 24.099611)
                                Log.e("空汙 ", "air p : $areaDis")
                                Log.e("minDistance ", "air p : $minDistance")
                                if (minDistance == 0.0f) {
                                    minDistance = areaDis
                                    minDistanceArea = "大里"
                                    minDistanceAir = airs[i].pm25!!
                                } else if (minDistance > areaDis) {
                                    minDistance = areaDis
                                    minDistanceArea = "大里"
                                    minDistanceAir = airs[i].pm25!!
                                }
                            }
                            airs[i].site.equals("沙鹿") -> {
                                val areaDis = getDistance(getLongitudeA, getLatitudeA, 120.568794, 24.225628)
                                Log.e("空汙 ", "air p : $areaDis")
                                Log.e("minDistance ", "air p : $minDistance")
                                if (minDistance == 0.0f) {
                                    minDistance = areaDis
                                    minDistanceArea = "沙鹿"
                                    minDistanceAir = airs[i].pm25!!
                                } else if (minDistance > areaDis) {
                                    minDistance = areaDis
                                    minDistanceArea = "沙鹿"
                                    minDistanceAir = airs[i].pm25!!
                                }
                            }
                            airs[i].site.equals("豐原") -> {
                                val areaDis = getDistance(getLongitudeA, getLatitudeA, 120.741711, 24.256586)
                                Log.e("空汙 ", "air p : $areaDis")
                                Log.e("minDistance ", "air p : $minDistance")
                                if (minDistance == 0.0f) {
                                    minDistance = areaDis
                                    minDistanceArea = "豐原"
                                    minDistanceAir = airs[i].pm25!!
                                } else if (minDistance > areaDis) {
                                    minDistance = areaDis
                                    minDistanceArea = "豐原"
                                    minDistanceAir = airs[i].pm25!!
                                }
                            }
                        }
                    }
                    air_quality_tv.text = "品質狀況:$minDistanceAir"
                    //切換圖示
                    when {
                        minDistanceAir.toDouble() <= 15.4 -> {
                            air_quality_img.setBackgroundResource(R.drawable.park256)
                            air_quality_tv.setTextColor(Color.parseColor("#215968"))
                        }
                        minDistanceAir.toDouble() <= 35.4 -> {
                            air_quality_img.setBackgroundResource(R.drawable.farm)
                            air_quality_tv.setTextColor(Color.parseColor("#6A6822"))
                        }
                        minDistanceAir.toDouble() <= 54.4 -> {
                            air_quality_img.setBackgroundResource(R.drawable.canyon)
                            air_quality_tv.setTextColor(Color.parseColor("#8B5403"))
                        }
                        minDistanceAir.toDouble() <= 150.4 -> {
                            air_quality_img.setBackgroundResource(R.drawable.desert)
                            air_quality_tv.setTextColor(Color.parseColor("#8D2B2B"))
                        }
                        minDistanceAir.toDouble() <= 250.4 -> {
                            air_quality_img.setBackgroundResource(R.drawable.volcano)
                            air_quality_tv.setTextColor(Color.parseColor("#66265D"))
                        }
                        else -> {
                            air_quality_img.setBackgroundResource(R.drawable.danger)
                            air_quality_tv.setTextColor(Color.parseColor("#6A2222"))
                        }
                    }
                }
                //清除資料
                minDistance = 0.0f
                minDistanceArea = ""
                minDistanceAir = ""
            }
            override fun onNothingSelected(parent: AdapterView<*>) {
            }
        }
    }

    //計算兩點距離
    fun getDistance(latitudeA: Double, longitudeA: Double, latitudeB: Double, longitudeB: Double): Float {
        val locationA = Location("point A")
        val locationB = Location("point B")

        //A點經、緯度
        locationA.longitude = longitudeA
        locationA.latitude = latitudeA

        //B點經、緯度
        locationB.longitude = longitudeB
        locationB.latitude = latitudeB

        val distance: Float = locationA.distanceTo(locationB)
        return distance
    }

    //取得xml資料
    fun getAssetsStream() {
        try {
            val tourData: InputStream = activity!!.assets.open("tour.xml")
            val xmlPullParser = Xml.newPullParser()
            tour = Tour()
            tours = ArrayList()
            nameList = ArrayList()
            nameList.add("請選擇旅遊地點")

            //xml解析器
            xmlPullParser.setInput(tourData, "utf-8")

            //取得xml節點
            var eventType = xmlPullParser.eventType

            //讀取xml資料
            while (eventType != XmlPullParser.END_DOCUMENT) {
                when (eventType) {
                    //開始讀檔案
                    XmlPullParser.START_DOCUMENT -> tours

                    //xml找到的節點儲存到list
                    XmlPullParser.START_TAG -> if (xmlPullParser.name == "RECORD") {

                        //節點-名稱
                    } else if (xmlPullParser.name == "名稱") {
                        val name = xmlPullParser.nextText()
                        tour.name = name
                        nameList.add(name)
                        //Log.e("tour name", "tour name: ${tour.name}")

                        //節點-區域
                    } else if (xmlPullParser.name == "鄉鎮市區") {
                        val area = xmlPullParser.nextText()
                        tour.area = area
                        //Log.e("tour area", "tour area: ${tour.area}")

                        //節點-地址
                    } else if (xmlPullParser.name == "地址") {
                        val addr = xmlPullParser.nextText()
                        tour.addr = addr
                        //Log.e("tour name", "tour name: ${tour.addr}")

                        //節點-經度
                    } else if (xmlPullParser.name == "東經") {
                        val eastL = xmlPullParser.nextText()
                        tour.eastL = eastL
                        //Log.e("tour name", "tour name: ${tour.eastL}")

                        //節點-緯度
                    } else if (xmlPullParser.name == "北緯") {
                        val northL = xmlPullParser.nextText()
                        tour.northL = northL
                        //Log.e("tour name", "tour name: ${tour.northL}")
                    }

                    //節點結束
                    XmlPullParser.END_TAG -> if (xmlPullParser.name == "RECORD") {
                        tours.add(tour)
                        tour = Tour()
                    }
                }
                //下一個xml節點
                eventType = xmlPullParser.next()
            }
            tourData.close()
        } catch (e: Exception) {
            e.printStackTrace()
        }
        //輸出內容
        for (i in 0 until tours.size) {
            Log.e("tour ", "tour $i xml : ${tours[i].name}")
        }
    }

    override fun onClick(view: View?) {

    }
}

這個部分完全使用本地資料,所以無法改變檢測站數據,有機會的話可能會使用retrofit來直接使用api取得所需資料來做判斷,這個部分就先告一段了。


上一篇
[Day 10] Android程式設計-使用OpenData資料製作app(六)(kotlin)
下一篇
[Day 12]Android自定義Listener(java)
系列文
Android的學習歷程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言